package com.example.websocket;

import com.alibaba.fastjson.JSON;
import com.example.util.MessageUtil;
import com.sun.deploy.util.StringUtils;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Huangyt
 * @version 1.0
 * @date 2020/9/19 21:39
 */
@ServerEndpoint(value = "/websocket", configurator = GetHttpSessionConfig.class /*获取HttpSession*/)
public class ChatSocket {
    private Session session; //WebSocket的Session
    private HttpSession httpSession; //Servlet中的Session,记录用户信息
    private static Map<HttpSession, ChatSocket> onlineUsers = new HashMap<>(); //维护所有聊天人员的HttpSession和EndPoint信息
    private static int onlineCount = 0; //记录聊天在线人数

    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        //1、记录WebSocket的会话信息对象Session
        this.session = session;
        //2、获取当前登录用户HttpSession信息
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        this.httpSession = httpSession;

        System.out.println("当前登录用户：" + httpSession.getAttribute("username") + "  EndPoint:" + config);

        //3、记录当前登录用户信息，及对应的Endpoint实例
        if (httpSession.getAttribute("username") != null) {
            onlineUsers.put(httpSession, this);
        }
        //4、获取当前所有登录用户（从onlineUsers中的httpSession获取username，并合并成以逗号分隔的字符串）
        String usernames = getNames();

        System.out.println("getNames():" + usernames);
        //5、组装消息（通过工具类将数据转化成JSON数据）
        String message = MessageUtil.getContent(MessageUtil.TYPE_USER, "", "", usernames);

        //6、通过广播的形式发送消息（调用WebSocket维护的Seesion对象的方法发送消息）
        boradcatAllUsers(message);

        //7、记录当前用户登陆数
        incrCount();
        System.out.println("onlineUsers.size:" + onlineUsers.size());
    }

    /*
        接收浏览器发送的消息
     */
    @OnMessage
    public void acceptMessage(String message, Session session) {
        System.out.println("message:" + message);
        //1、获取客户端消息内容，并解析
        Map<String, String> msgMap = JSON.parseObject(message, Map.class);
        String fromName = msgMap.get("fromName");
        String toName = msgMap.get("toName");
        String content = msgMap.get("content");
        //2、判定消息是否有接收人
        if(toName==null||toName.isEmpty()){
            return;
        }
        String msg = MessageUtil.getContent(MessageUtil.TYPE_MESSAGE, fromName, toName, content);
        //3、判定消息接收人是否为广播（“all”），则说明发送广播消息
        if("all".equals(toName)){
            //3.1、组装消息内容
            System.out.println("广播发送：" + content);
            boradcatAllUsers(msg);
        }
        //4、不是all，则给指定用户推送消息
        else {
            System.out.println("指定客户端发送：" + content);
            //4.1、组装消息内容
            singleSend(msg, fromName, toName);
        }
    }

    /*
        关闭WebSocket连接
     */
    @OnClose
    public void onClose(Session session, CloseReason closeReason){
        decrCount();
        System.out.println("客户端关闭了一个连接，当前在线人数：" + getOnlineCount());
    }

    @OnError
    public void onError(Session session, Throwable throwable){
        throwable.printStackTrace();
        System.out.println("服务异常...");
    }

    private void singleSend(String message, String fromName, String toName) {
        Boolean flag = false;

        //判定接收人是否在线，不在线直接退出
        for(HttpSession httpSession : onlineUsers.keySet()){
            if(httpSession.getAttribute("username").equals(toName)){
                flag = true;
                break;
            }
        }

        //接收人在线，给发送消息的和接收消息的发送消息（双方都要显示消息内容）
        if(flag){
            int count = 0;
            for(HttpSession httpSession : onlineUsers.keySet()){
                if(count==2){
                    break;
                }
                if(httpSession.getAttribute("username").equals(toName)||httpSession.getAttribute("username").equals(fromName)){
                    ChatSocket chatSocket = onlineUsers.get(httpSession);
                    try {
                        chatSocket.session.getBasicRemote().sendText(message);
                        count++;
                        System.out.println("发送成功..." + count);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private void boradcatAllUsers(String message) {
        onlineUsers.forEach((k, v) -> {
            try {
                v.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    private String getNames() {
        String names = "";
        if (onlineUsers.size() > 0) {
            for (HttpSession httpSession : onlineUsers.keySet()) {
                String username = (String) httpSession.getAttribute("username");
                names += username + ",";
            }
        }
        String usernames = names.substring(0, names.length() - 1);
        return usernames;
    }

    public int getOnlineCount() {
        return onlineCount;
    }

    public synchronized void incrCount() {
        onlineCount = onlineUsers.size();
    }

    public synchronized void decrCount() {
        onlineCount--;
    }

}

